package com.dc.designPattern._999_multi_pattern.demo_1.price;

import cn.hutool.core.util.ClassUtil;
import com.dc.designPattern._999_multi_pattern.demo_1.Player;
import com.dc.designPattern._999_multi_pattern.demo_1.price.anno.PriceRegion;

import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Description: 价格工厂
 * @author: gdc
 * @date: 2021/6/10
 * @version 1.0
 */
public class CalPriceFactory {

    /**
     * 价格类包路径
     */
    private String PRICE_PATH = "com.dc.designPattern._999_multi_pattern.demo_1.price";

    /**
     * 价格类集合
     */
    private static Set<Class<? extends CalPrice>> calPriceClassSet;

    // ----------------------------------工厂模式 start----------------------------------------

    /**
     * 获取具体的价格策略
     * @param player
     * @return
     */
    public static CalPrice create(Player player){
        for (Class<? extends CalPrice> clazz : calPriceClassSet) {
            PriceRegion priceRegion = clazz.getAnnotation(PriceRegion.class);
            if (Objects.nonNull(priceRegion) && player.getTotalAmount() >= priceRegion.min() && player.getTotalAmount() < priceRegion.max()) {
                try {
                    return clazz.newInstance();
                } catch (Exception e) {
                    throw new RuntimeException("策略获取失败");
                }
            }
        }
        throw new RuntimeException("策略获取失败");
    }
    // ----------------------------------工厂模式 end----------------------------------------

    // ----------------------------------单例模式_静态内部类 start----------------------------------------
    /**
     * 获取 价格工厂实例
     * @return          价格工厂
     */
    public static CalPriceFactory getInstance() {
        return CalPriceFactoryInstance.INSTANCE;
    }

    private CalPriceFactory() {
        init();
    }

    private static class CalPriceFactoryInstance{
        private static CalPriceFactory INSTANCE = new CalPriceFactory();
    }
    // ----------------------------------单例模式_静态内部类 end----------------------------------------

    /**
     * 初始化调用方法，完成对价格类信息的获取
     */
    private void init(){
        calPriceClassSet = ClassUtil.scanPackage(PRICE_PATH).stream()
                .filter(clazz -> CalPrice.class.isAssignableFrom(clazz) && clazz != CalPrice.class)
                .map(clazz -> (Class<? extends CalPrice>)clazz)
                .collect(Collectors.toSet());
    }
}